package el.util.force;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import prefuse.util.force.ForceItem;
import prefuse.util.force.ForceSimulator;

public class WholeNBodyForceMultiThread extends WholeNBodyForce {

	public int cores;
	public WholeNBodyForceRunnable[] wholeForces;
	ExecutorService exec;

	public WholeNBodyForceMultiThread(int cores, ExecutorService exec) {
		super();
		this.wholeForces = new WholeNBodyForceRunnable[cores];
		for (int i = 0; i < cores; i++) {
			this.wholeForces[i] = new WholeNBodyForceRunnable(i, cores);
		}
		this.cores = cores;
		this.exec = exec;
	}

	public void init(ForceSimulator fsim) {
		for (int i = 0; i < cores; i++)
			wholeForces[i].init(fsim);
	}

	public void init(List<ForceItem> list) {
		for (int i = 0; i < cores; i++)
			wholeForces[i].init(list.iterator());
	}

	public void clear() {
		for (int i = 0; i < cores; i++)
			wholeForces[i].clear();
	}

	/**
	 * Calculates the force vector acting on the given item.
	 * 
	 * @param item
	 *            the ForceItem for which to compute the force
	 */
	public void getForce(ForceItem item) {
		List<Future<Integer>> res = new ArrayList<Future<Integer>>();
		
		/*
		res.add(exec.submit(wholeForces[0]));
		try {
			res.get(0).get();
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
		
		
		for (int i = 0; i < cores; i++) {
			res.add(exec.submit(wholeForces[i]));
		}
		
		
		try {
			for (Future<Integer> s : res) {
				s.get();
			}
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public static void main(String[] argv) {
		ExecutorService exec = Executors.newFixedThreadPool(4);
		class A implements Callable<Integer> {

			public Integer call() {
				System.out.println("Fuck you.");
				return 3;
			}
		}

		int num = 10;
		A[] a = new A[num];
		List<Future<Integer>> res = new ArrayList<Future<Integer>>();
		for (int i = 0; i < num; i++) {
			a[i] = new A();
			res.add(exec.submit(a[0]));
			System.out.println("Submit\t" + i);
		}

		try {
			for (Future<Integer> s : res) {
				System.out.println(s.get());
			}
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		exec.shutdownNow();
		System.out.println("Finished");

	}
}
